package com.zone.infrastructure.persistent.repository;

import com.google.common.collect.Lists;
import com.google.gson.Gson;
import com.zone.domain.rebate.event.UserRebateEvent;
import com.zone.domain.rebate.model.aggregate.UserRebateCreateOrderAggregate;
import com.zone.domain.rebate.model.entity.DailyBehaviorRebateEntity;
import com.zone.domain.rebate.model.entity.UserBehaviorRebateOrderEntity;
import com.zone.domain.rebate.model.valobj.BehaviorTypeEnum;
import com.zone.domain.rebate.model.valobj.DailyBehaviorRebateState;
import com.zone.domain.rebate.model.valobj.RebateTypeEnum;
import com.zone.domain.rebate.repository.IBehaviorRebateRepository;
import com.zone.domain.task.model.entity.TaskEntity;
import com.zone.domain.task.model.valobj.TaskState;
import com.zone.infrastructure.event.MessageProduct;
import com.zone.infrastructure.persistent.dao.IDailyBehaviorRebateDao;
import com.zone.infrastructure.persistent.dao.ITaskDao;
import com.zone.infrastructure.persistent.dao.IUserBehaviorRebateOrderDao;
import com.zone.infrastructure.persistent.po.DailyBehaviorRebate;
import com.zone.infrastructure.persistent.po.Task;
import com.zone.infrastructure.persistent.po.UserBehaviorRebateOrder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.support.TransactionTemplate;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author: zongzi
 * @description: TODO
 * @date: 2025/3/3
 */
@Slf4j
@Repository
public class BehaviorRebateRepository implements IBehaviorRebateRepository {
    @Autowired
    private IDailyBehaviorRebateDao dailyBehaviorRebateDao;
    @Autowired
    private IUserBehaviorRebateOrderDao userBehaviorRebateOrderDao;
    @Autowired
    private ITaskDao taskDao;
    @Autowired
    private TransactionTemplate transactionTemplate;
    @Value("${spring.rabbitmq.topic.user_rebate}")
    private String userRebateTopic;
    @Autowired
    private MessageProduct messageProduct;

    @Override
    public List<DailyBehaviorRebateEntity> queryDailyBehaviorRebate(BehaviorTypeEnum behaviorType) {
        List<DailyBehaviorRebate> dailyBehaviorRebates = dailyBehaviorRebateDao.queryDailyBehaviorRebate(behaviorType.getCode());
        if (CollectionUtils.isEmpty(dailyBehaviorRebates)) {
            return Lists.newArrayList();
        }
        return dailyBehaviorRebates.stream()
                .map(dailyBehaviorRebate -> {
                    DailyBehaviorRebateEntity dailyBehaviorRebateEntity = new DailyBehaviorRebateEntity();
                    dailyBehaviorRebateEntity.setBehaviorType(BehaviorTypeEnum.valueOf(dailyBehaviorRebate.getBehaviorType()));
                    dailyBehaviorRebateEntity.setRebateDesc(dailyBehaviorRebate.getRebateDesc());
                    dailyBehaviorRebateEntity.setRebateType(RebateTypeEnum.valueOf(dailyBehaviorRebate.getRebateType()));
                    dailyBehaviorRebateEntity.setRebateConfig(dailyBehaviorRebate.getRebateConfig());
                    dailyBehaviorRebateEntity.setState(DailyBehaviorRebateState.valueOf(dailyBehaviorRebate.getState()));
                    return dailyBehaviorRebateEntity;
                }).collect(Collectors.toList());
    }

    @Override
    public void createRebateOrder(List<UserRebateCreateOrderAggregate> createOrderAggregates) {
        List<UserBehaviorRebateOrder> userBehaviorRebateOrders = Lists.newArrayList();
        List<Task> taskList = Lists.newArrayList();
        for (UserRebateCreateOrderAggregate userRebateCreateOrderAggregate : createOrderAggregates) {
            // 返利流水单
            UserBehaviorRebateOrderEntity userBehaviorRebateOrderEntity = userRebateCreateOrderAggregate.getUserBehaviorRebateOrderEntity();
            UserBehaviorRebateOrder userBehaviorRebateOrder = new UserBehaviorRebateOrder();
            userBehaviorRebateOrder.setUserId(userBehaviorRebateOrderEntity.getUserId());
            userBehaviorRebateOrder.setOrderId(userBehaviorRebateOrderEntity.getOrderId());
            userBehaviorRebateOrder.setBehaviorType(userBehaviorRebateOrderEntity.getBehaviorType().getCode());
            userBehaviorRebateOrder.setRebateDesc(userBehaviorRebateOrderEntity.getRebateDesc());
            userBehaviorRebateOrder.setRebateType(userBehaviorRebateOrderEntity.getRebateType().getCode());
            userBehaviorRebateOrder.setRebateConfig(userBehaviorRebateOrderEntity.getRebateConfig());
            userBehaviorRebateOrder.setBizId(userBehaviorRebateOrderEntity.getBizId());
            userBehaviorRebateOrder.setOutBusinessNo(userBehaviorRebateOrderEntity.getOutBusinessNo());
            userBehaviorRebateOrder.setOrderDate(userBehaviorRebateOrderEntity.getOrderDate());
            userBehaviorRebateOrders.add(userBehaviorRebateOrder);

            TaskEntity taskEntity = userRebateCreateOrderAggregate.getTaskEntity();
            Task task = new Task();
            task.setUserId(taskEntity.getUserId());
            task.setTopic(taskEntity.getTopic());
            task.setMessageId(taskEntity.getMessageId());
            task.setMessage(taskEntity.getMessage());
            task.setState(taskEntity.getState().getCode());
            taskList.add(task);
        }

        // 保存流水单
        transactionTemplate.execute(status -> {
            try {
                userBehaviorRebateOrderDao.batchInsert(userBehaviorRebateOrders);
                // 保存task
                taskDao.batchInsert(taskList);
                return 1;
            } catch (Exception e) {
                status.setRollbackOnly();
                throw e;
            }
        });
        taskList.forEach(task -> {
            try {
                // 发送mq
                Gson gson = new Gson();
                UserRebateEvent userRebateEvent = gson.fromJson(task.getMessage(), UserRebateEvent.class);
                messageProduct.sendMessage(userRebateTopic, userRebateEvent);
                // 更新task状态
                task.setState(TaskState.COMPLETED.getCode());
                taskDao.updateStateByMessageId(task);
            } catch (Exception e) {
                log.error("创建用户返利流水单，发送消息失败", e);
                // 更新task状态
                task.setState(TaskState.FAIL.getCode());
                taskDao.updateStateByMessageId(task);
            }
        });
    }

    @Override
    public List<UserBehaviorRebateOrderEntity> queryUserBehaviorRebateOrderList(String userId, BehaviorTypeEnum behaviorType, LocalDate orderDate) {
        List<UserBehaviorRebateOrder> userBehaviorRebateOrders = userBehaviorRebateOrderDao.queryByUserIdAndBehaviorTypeAndOrderDate(userId, behaviorType.getCode(), orderDate);
        if (CollectionUtils.isEmpty(userBehaviorRebateOrders)) {
            return Lists.newArrayList();
        }
        return userBehaviorRebateOrders.stream()
                .map(userBehaviorRebateOrder -> {
                    UserBehaviorRebateOrderEntity userBehaviorRebateOrderEntity = new UserBehaviorRebateOrderEntity();
                    userBehaviorRebateOrderEntity.setUserId(userBehaviorRebateOrder.getUserId());
                    userBehaviorRebateOrderEntity.setOrderId(userBehaviorRebateOrder.getOrderId());
                    userBehaviorRebateOrderEntity.setBehaviorType(BehaviorTypeEnum.valueOf(userBehaviorRebateOrder.getBehaviorType()));
                    userBehaviorRebateOrderEntity.setRebateDesc(userBehaviorRebateOrder.getRebateDesc());
                    userBehaviorRebateOrderEntity.setRebateType(RebateTypeEnum.valueOf(userBehaviorRebateOrder.getRebateType()));
                    userBehaviorRebateOrderEntity.setRebateConfig(userBehaviorRebateOrder.getRebateConfig());
                    userBehaviorRebateOrderEntity.setBizId(userBehaviorRebateOrder.getBizId());
                    userBehaviorRebateOrderEntity.setOutBusinessNo(userBehaviorRebateOrder.getOutBusinessNo());
                    userBehaviorRebateOrderEntity.setOrderDate(userBehaviorRebateOrder.getOrderDate());
                    return userBehaviorRebateOrderEntity;
                }).collect(Collectors.toList());
    }
}
